package api

import (
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"math"
	"net/http"
	"strconv"
	"time"
	. "xm_shop/database"
	. "xm_shop/models"
)

type UserController struct{}

func (u UserController) Index(context *gin.Context) {

}

// 订单列表
func (u UserController) OrderList(context *gin.Context) {
	page, err1 := strconv.Atoi(context.Query("page"))
	if err1 != nil {
		context.String(http.StatusBadRequest, "参数有误")
		return
	}
	// 获取当前用户
	var user User
	Cookie.Get(context, "userInfo", &user)
	where := "uid=" + strconv.Itoa(user.ID)
	keywords := context.Query("keywords")
	if keywords != "" {
		// 查询
		var orderItems []OrderItem
		DB.Where("product_title like ?", "%"+keywords+"%").Find(&orderItems)
		var str string
		for i := 0; i < len(orderItems); i++ {
			if i == 0 {
				str += strconv.Itoa(orderItems[i].OrderId)
			} else {
				str += "," + strconv.Itoa(orderItems[i].OrderId) // 1,2,3,4,5,6
			}
		}
		where += " AND id in (" + str + ")"
	}
	// 按照状态筛选订单
	orderStatus, err2 := strconv.Atoi(context.Query("order_status"))
	if err2 == nil && orderStatus >= 0 {
		where += " AND order_status=" + strconv.Itoa(orderStatus)
	} else {
		orderStatus = -1
	}

	pageSize := 5
	// 获取当前用户下的订单信息
	var orderList []Order
	DB.Where(where).Offset((page - 1) * pageSize).Limit(pageSize).Preload("OrderItems").Order("add_time DESC").Find(&orderList)
	// 获取总数量
	var count int64
	DB.Table("order").Where("uid = ?", user.ID).Count(&count)

	urlPath := context.Request.URL.Path
	context.JSON(http.StatusOK, gin.H{
		"orderList":   orderList,
		"page":        page,
		"keywords":    keywords,
		"orderStatus": orderStatus,
		"urlPath":     urlPath,
		"totalPage":   math.Ceil(float64(count) / float64(pageSize)),
	})
}

// 获取指定订单
func (u UserController) OrderInfo(context *gin.Context) {
	id, err1 := strconv.Atoi(context.Param("id"))
	if err1 != nil {
		context.String(http.StatusBadRequest, "参数有误")
		return
	}
	// 获取用户信息
	var user User
	Cookie.Get(context, "userInfo", &user)
	// 检索订单
	var order Order
	DB.Where("id = ? AND uid = ?", id, user.ID).Preload("OrderItems").Take(&order)
	if order.ID == 0 {
		context.String(http.StatusBadRequest, "订单不存在")
		return
	}
	context.JSON(http.StatusOK, gin.H{
		"order": order,
	})
}

// 1. 需要先定义一个结构体, 这个结构体需要继承jwt.StandardClaims 结构体
type MyClaims struct {
	Uid int
	jwt.StandardClaims
}

// 2. 定义key
var jwtKey = []byte("123456")

// 生成token
func (u UserController) Test(context *gin.Context) {

	// 3.定义到期时间
	var expireTime = time.Now().Add(24 * time.Hour).Unix()
	// 4. 实例化存储token的结构体
	myClaims := MyClaims{
		Uid: 23, // 自定义字段
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expireTime, // 配置到期时间(建议必填)
			Issuer:    "zj",       // 配置签发人(选填)
		},
	}
	// 使用指定的签名方法创建签名对象
	tokenObj := jwt.NewWithClaims(jwt.SigningMethodHS256, myClaims) // 签名对象
	tokenStr, err := tokenObj.SignedString(jwtKey)                  // 签名对象利用密钥进行加密, 返回加密后的字符串token
	if err != nil {
		context.String(http.StatusBadRequest, "加密失败")
		return
	}
	context.String(http.StatusOK, tokenStr)
}

// 验证token
func (u UserController) T2(context *gin.Context) {
	//tokenStr := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVaWQiOjIzLCJleHAiOjE3MjA0NDc3NjAsImlzcyI6InpqIn0.l84F4ZK9cJysxycolHi09qtEE3UXP3JPxh5dA4lAdc4"
	// 获取token
	tokenStr := context.Request.Header.Get("Authorization") // 可以用长度判断是否存在
	token, myClaims, err := ParseToken(tokenStr)
	if err != nil || !token.Valid {
		context.String(http.StatusBadRequest, "token异常")
		return
	}
	fmt.Println(myClaims)
	context.JSON(http.StatusOK, gin.H{
		"myClaims": myClaims,
	})
}

// 验证token是否合法
func ParseToken(tokenStr string) (*jwt.Token, *MyClaims, error) {
	s := &MyClaims{}
	token, err := jwt.ParseWithClaims(tokenStr, s, func(token *jwt.Token) (interface{}, error) { // 解密token
		return jwtKey, nil // 固定写法
	})
	return token, s, err
}
